#include <schedule.h>
#include <8259A.h>
#include <task.h>
#include <desc.h>
#include <share.h>
#include <queue.h>


/******************************************************************************
* 函数名称: void schedule(void)
* 功能说明: 进程调度
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void schedule(void)
{
    QUEUE_NODE* nodeTmp = NULL;

    if(current_task->current < current_task->total)
        current_task->current++;
    else
    {
        current_task->current = 0;
        // 从就绪任务队列中取出一个任务节点并执行该任务，再将该任务节点重新添加到就绪任务队列中
        nodeTmp = QueueRemove(&TASK_READY_QUEUE);
        current_task = (volatile TASK *)QUEUE_NODE(nodeTmp, TASK, node);
        QueueAdd(&TASK_READY_QUEUE, nodeTmp);

        TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR);                             // 找到 TSS
        tss->esp0 = (U32)(&current_task->reg) + sizeof(current_task->reg);    // TSS.esp0 指向任务上下文数据结构 reg 的末尾
        current_reg = (U32)(&current_task->reg);                              // current_reg 指向任务上下文数据结构 reg 的起始位置
    }
}

/******************************************************************************
* 函数名称: E_RET MutexSuspend(MUTEX* mutex)
* 功能说明: 将当前任务节点从任务就绪队列中转移到互斥锁的等待队列中
* 输入参数: MUTEX* mutex        --互斥锁
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET MutexSuspend(MUTEX* mutex)
{
    QUEUE_NODE* nodeTmp = NULL;

    // 把当前任务节点从就绪任务队列中取出，当前任务节点在队列尾，取出后添加到互斥锁 mutex 的 wait 等待队列中
    nodeTmp = QueueTailRemove(&TASK_READY_QUEUE);
    if(NULL == nodeTmp)
        return E_ERR;
    QueueAdd(&mutex->wait, nodeTmp);  // 这是该函数与 SYS_TaskDestory 函数的唯一区别

    // 从就绪任务队列中取出一个任务节点并执行该任务，再将该任务节点重新添加到就绪任务队列中
    nodeTmp = QueueRemove(&TASK_READY_QUEUE);
    if(NULL == nodeTmp)
        return E_ERR;
    current_task = (volatile TASK *)QUEUE_NODE(nodeTmp, TASK, node);
    QueueAdd(&TASK_READY_QUEUE, nodeTmp);

    TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR);                             // 找到 TSS
    tss->esp0 = (U32)(&current_task->reg) + sizeof(current_task->reg);    // TSS.esp0 指向任务上下文数据结构 reg 的末尾
    current_reg = (U32)(&current_task->reg);                              // current_reg 指向任务上下文数据结构 reg 的起始位置
    SWITCH_TO(current_task);
    
    return E_OK;
}

/******************************************************************************
* 函数名称: E_RET MutexResume(MUTEX* mutex)
* 功能说明: 将互斥锁等待队列中的任务转移到任务就绪队列中
* 输入参数: MUTEX* mutex        --互斥锁
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET MutexResume(MUTEX* mutex)
{
    QUEUE_NODE* nodeTmp = NULL;

    // 从互斥锁的等待队列中取出一个任务，并将其添加到就绪队列中
    nodeTmp = QueueRemove(&mutex->wait);
    if(NULL == nodeTmp)
        return E_ERR;
    QueueHeadAdd(&TASK_READY_QUEUE, nodeTmp);

    return E_OK;
}

/******************************************************************************
* 函数名称: void Int0x20Handle(void)
* 功能说明: 0x20 号中断中断服务程序的逻辑功能部分
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void Int0x20Handle(void)
{
    schedule();
    write_m_EOI();  
}

